package user_role

import (
	"errors"
	"cgs-server/server"
	"cgs-server/server/base"
	"cgs-server/server/model"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
)

type UserRoleRepository interface {
	base.Repository
	FindByUserId(userId primitive.ObjectID) (*model.UserRoleList, error) // 根据 userId 获取
	FindByRoleId(roleId primitive.ObjectID) (*model.UserRoleList, error) // 根据 roleId 获取
	// 根据 userId 更新
	UpdateByUserId(user *model.User) error
	// 根据 userId 删除
	DeleteByUserId(userId string) error
	// 根据 roleId 删除
	DeleteByRoleId(roleId string) error

	// 根据 roleIds 删除
	BatchDeleteByRoleIds(roleIds []string) error

	// 更新角色下的用户
	UpdateByRole(role *model.Role) error
}

func NewUserRoleRepository() UserRoleRepository {
	return &userRoleRepository{base.RepositoryStruct{
		CollectionName: server.UserRole,
	}}
}

type userRoleRepository struct {
	base.RepositoryStruct
}

func (ur *userRoleRepository) FindByUserId(userId primitive.ObjectID) (*model.UserRoleList, error) {
	if err := ur.CheckDB(); err != nil {
		return nil, err
	}
	filter := bson.M{
		"userId": userId.Hex(),
	}
	userRoleList := &model.UserRoleList{}
	err := ur.Mongo.FindMany(ur.CollectionName, filter, userRoleList)
	return userRoleList, err
}

func (ur *userRoleRepository) FindByRoleId(roleId primitive.ObjectID) (*model.UserRoleList, error) {
	if err := ur.CheckDB(); err != nil {
		return nil, err
	}
	filter := bson.M{
		"roleId": roleId.Hex(),
	}
	userRoleList := &model.UserRoleList{}
	err := ur.Mongo.FindMany(ur.CollectionName, filter, userRoleList)
	return userRoleList, err
}

func (ur *userRoleRepository) FindOne(mdl *model.DataUserModel) (interface{}, error) {
	if userRole, ok := mdl.Data.(*model.UserRole); ok {
		if err := ur.CheckDB(); err != nil {
			return nil, err
		}
		filter := bson.M{}
		if userRole.UserId != "" {
			filter["userId"] = userRole.UserId
		}
		if userRole.RoleId != "" {
			filter["roleId"] = userRole.RoleId
		}
		if mdl.Filter != nil {
			filter = *mdl.Filter
		}
		result := &model.UserRole{}
		find, err := ur.Mongo.FindOne(ur.CollectionName, filter, result)
		if find {
			return result, nil
		}
		return nil, err
	} else {
		return nil, model.NewTypeError("UserRole")
	}
}

func (ur *userRoleRepository) UpdateByUserId(user *model.User) error {
	if err := ur.CheckDB(); err != nil {
		return err
	}
	if user.Roles == nil {
		return errors.New("roles is nil")
	}
	// 删除所有用户关联的角色信息
	filter := bson.M{
		"userId": user.UserId,
	}
	_, err := ur.Mongo.DeleteMany(ur.CollectionName, filter)
	if err != nil {
		return err
	}

	// 添加新的关联信息
	if len(*user.Roles) == 0 {
		return nil
	}
	data := make([]interface{}, len(*user.Roles))
	for idx, role := range *user.Roles {
		data[idx] = model.UserRole{
			UserId: user.UserId.Hex(),
			RoleId: role.Id.Hex(),
		}
	}
	_, err = ur.Mongo.InsertMany(ur.CollectionName, data)
	return err
}

func (ur *userRoleRepository) DeleteByUserId(userId string) error {
	if err := ur.CheckDB(); err != nil {
		return err
	}
	filter := bson.M{
		"userId": userId,
	}
	_, err := ur.Mongo.DeleteMany(ur.CollectionName, filter)
	return err
}

func (ur *userRoleRepository) DeleteByRoleId(roleId string) error {
	if err := ur.CheckDB(); err != nil {
		return err
	}
	filter := bson.M{
		"roleId": roleId,
	}
	_, err := ur.Mongo.DeleteMany(ur.CollectionName, filter)
	return err
}

func (ur *userRoleRepository) BatchDeleteByRoleIds(roleIds []string) error {
	if err := ur.CheckDB(); err != nil {
		return err
	}
	filter := bson.M{
		"roleId": bson.M{
			"$in": roleIds,
		},
	}
	_, err := ur.Mongo.DeleteMany(ur.CollectionName, filter)
	return err
}

func (ur *userRoleRepository) UpdateByRole(role *model.Role) error {
	if err := ur.CheckDB(); err != nil {
		return err
	}
	if role.UserIds == nil {
		return errors.New("UserIds is nil")
	}
	// 删除所有用户关联的角色信息
	filter := bson.M{
		"roleId": role.Id.Hex(),
	}
	_, err := ur.Mongo.DeleteMany(ur.CollectionName, filter)
	if err != nil {
		return err
	}

	// 添加新的关联信息
	if len(role.UserIds) == 0 {
		return nil
	}
	data := make([]interface{}, len(role.UserIds))
	for idx := range role.UserIds {
		data[idx] = model.UserRole{
			UserId: role.UserIds[idx],
			RoleId: role.Id.Hex(),
		}
	}
	_, err = ur.Mongo.InsertMany(ur.CollectionName, data)
	return err
}
